#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
// #include "protocol_examples_common.h"
#include "esp_mac.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "sdkconfig.h"
#include "mbedtls/md5.h"
#include <cJSON.h>
#include "esp_http_client.h"
// #include "string.h"
// #include "cstring"
#include "stdlib.h"
#include<iostream>
using namespace std;
// #include "esp_chip_info.h"
static const char *TAG = "example";

#define MAX_HTTP_OUTPUT_BUFFER 2048 // http最大数据接收大小
bool gettime = true;                // 是否从网络请求时间
class Device {
public:
    std::string device_id;
    std::string device_key;

    // 序列化为 JSON 字符串
    std::string serializeToJson() const {
        cJSON *root = cJSON_CreateObject();
        cJSON_AddStringToObject(root, "device_id", device_id.c_str());
        cJSON_AddStringToObject(root, "device_key", device_key.c_str());
        char *json_str = cJSON_Print(root);
        std::string result(json_str);
        cJSON_Delete(root);
        free(json_str);
        return result;
    }

    // 从 JSON 字符串反序列化
    bool deserializeFromJson(const std::string& json) {
        cJSON *root = cJSON_Parse(json.c_str());
        if (root == nullptr) {
            return false;
        }
        cJSON *id = cJSON_GetObjectItem(root, "device_id");
        cJSON *key = cJSON_GetObjectItem(root, "device_key");
        if (id != nullptr && key != nullptr) {
            device_id = id->valuestring;
            device_key = key->valuestring;
        }
        cJSON_Delete(root);
        return true;
    }
};
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
    cJSON *pMacAdress = NULL;
#if 0
//switch判断事件代码提示出错可以写成if方式
    switch (evt->event_id)
    {
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER");
            printf("%.*s", evt->data_len, (char *)evt->data);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA,len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client))
            {
                printf("%.*s", evt->data_len, (char *)evt->data);
            }
            break;
        case HTTP_EVENT_ON_FINISH://http完成事件
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
            break;
        case HTTP_EVENT_DISCONNECTED://http断开连接事件
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            break;
    }
#endif
    if (evt->event_id == HTTP_EVENT_ON_DATA) // 收到数据事件
    {

        ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA,len=%d", evt->data_len);
        if (!esp_http_client_is_chunked_response(evt->client))
        {
            ESP_LOGI(TAG, "响应:%s------", (char *)evt->data);
            cJSON *pJsonRoot = cJSON_Parse((const char *)(evt->data)); // cJSON解析json格式数据

            if (pJsonRoot != NULL) // 如果是否json格式数据
            {
                pMacAdress = cJSON_GetObjectItem(pJsonRoot, "api"); // 解析字段字符串内容
                if (pMacAdress != NULL)
                {
                    if (cJSON_IsString(pMacAdress)) // 判断字段是否string类型
                    {
                        ESP_LOGI(TAG, "api = %s", pMacAdress->valuestring);
                    }
                }
                pMacAdress = cJSON_GetObjectItem(pJsonRoot, "v"); // 解析字段字符串内容
                if (pMacAdress != NULL)
                {
                    if (cJSON_IsString(pMacAdress)) // 判断字段是否string类型
                    {
                        ESP_LOGI(TAG, "v = %s", pMacAdress->valuestring);
                    }
                }
                pMacAdress = cJSON_GetObjectItem(pJsonRoot, "ret");
                if (pMacAdress != NULL)
                {
                    // ret的数据应该怎么提取,不知道.有知道的朋友麻烦留言告知
                }
                pMacAdress = cJSON_GetObjectItem(pJsonRoot, "data"); // 解析字段字符串内容
                if (pMacAdress != NULL)
                {
                    cJSON *pSub_2 = cJSON_GetObjectItem(pMacAdress, "t");
                    if (pSub_2 != NULL)
                    {
                        if (cJSON_IsString(pSub_2)) // 判断字段是否string类型
                        {
                            ESP_LOGI(TAG, "data/t = %s", pSub_2->valuestring);
                        }
                    }
                }
            }
            else
            {
                ESP_LOGI(TAG, "数据错误,不是JSon格式");
            }

            cJSON_Delete(pJsonRoot);
        }
    }
    return ESP_OK;
}
void http_get_task(void *pvParameters)
{
    mbedtls_md5_context md5_ctx;
    mbedtls_md5_init(&md5_ctx);
    unsigned char input_data[] = "hello_world1234"; // 输入数据
    unsigned char output_data[16]; // MD5 输出结果（16 字节）

    // 开始 MD5 加密
    mbedtls_md5_starts(&md5_ctx);
    // 更新数据
    mbedtls_md5_update(&md5_ctx, input_data, strlen((char *)input_data));
    // 完成 MD5 加密
    mbedtls_md5_finish(&md5_ctx, output_data);

    printf("MD5 加密前: [%s]\n", input_data);
    printf("MD5 加密后 (32 位): ");
    for (int i = 0; i < 16; i++) {
        printf("%02x", output_data[i]);
    }
    printf("\n");
    mbedtls_md5_free(&md5_ctx);

    uint8_t mac[6] = {0};
    esp_err_t ret = esp_read_mac(mac, ESP_MAC_WIFI_STA);
    if (ret == ESP_OK) {
        ESP_LOGI("MAC Address", "MAC: %02x:%02x:%02x:%02x:%02x:%02x",
                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    } else {
        ESP_LOGE("MAC Address", "Failed to read MAC address");
    }

    nvs_handle_t my_handle;
    esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle);
    if (err != ESP_OK) {
        ESP_LOGE("NVS", "Error (%s) opening NVS handle!", esp_err_to_name(err));
        return;
    }
    //存整数
    // err = nvs_set_i32(my_handle, "key", 42);
    // if (err != ESP_OK) {
    //     ESP_LOGE("NVS", "Error (%s) writing to NVS!", esp_err_to_name(err));
    // }
    //存字符串
    err = nvs_set_str(my_handle, "ma", "my_wifi_ssid");
    if (err != ESP_OK) {
        ESP_LOGE("NVS", "Error (%s) writing to NVS!", esp_err_to_name(err));
    }
    //提交更改
    err = nvs_commit(my_handle);
    if (err != ESP_OK) {
        ESP_LOGE("NVS", "Error (%s) committing to NVS!", esp_err_to_name(err));
    }
    // nvs_close(my_handle);
    //读取字符串
    size_t required_size;
    err = nvs_get_str(my_handle, "ma", NULL, &required_size);
    if (err != ESP_OK) {
        ESP_LOGE("NVS", "Error (%s) reading from NVS!", esp_err_to_name(err));
        return;
    }
    

    char *ssid = (char*)malloc(required_size);
    if (ssid == NULL) {
        ESP_LOGE("NVS", "Memory allocation failed");
        return;
    }

    err = nvs_get_str(my_handle, "ma", ssid, &required_size);
    if (err == ESP_OK) {
        ESP_LOGI("NVS", "SSID = %s", ssid);
    } else {
        ESP_LOGE("NVS", "Error (%s) reading from NVS!", esp_err_to_name(err));
    }
    nvs_close(my_handle);
    free(ssid);



    //序列化
    Device device;
    device.device_id = "12345";
    device.device_key = "abcdef";

    // 序列化为 JSON
    std::string json = device.serializeToJson();
    std::cout << "Serialized JSON: " << json << std::endl;

    // 反序列化
    Device new_device;
    if (new_device.deserializeFromJson(json)) {
        std::cout << "Deserialized Device: " << std::endl;
        std::cout << "Device ID: " << new_device.device_id << std::endl;
        std::cout << "Device Key: " << new_device.device_key << std::endl;
    } else {
        std::cerr << "Failed to deserialize JSON." << std::endl;
    }
    SemaphoreHandle_t bind_ok;
    bind_ok = xSemaphoreCreateCounting(1, 0);
    while (xSemaphoreTake(bind_ok, portMAX_DELAY) != pdTRUE)
    {
        ESP_LOGI(TAG, "发送http请求");
        char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
       
        
        // snprintf(url, sizeof(url), "http://6d90b9da.r12.cpolar.top/api/v1/device/%s?param1=value1&param2=value2", path_param);
        esp_http_client_config_t config = {
            .url = "http://6d90b9da.r12.cpolar.top/api/v1/device/bind", 
            .method = HTTP_METHOD_POST, // get方式请求数据
            .event_handler = _http_event_handler,
            .user_data = local_response_buffer,
                       
           
        };
        esp_http_client_handle_t client = esp_http_client_init(&config);
        char post_data[] = "{\"device_id\":\"999\",\"device_key\":\"b706835de79a2b4e80506f582af3676a\"}";
        esp_http_client_set_header(client, "Content-Type", "application/json");
        esp_http_client_set_post_field(client, post_data, strlen(post_data));
        esp_err_t err = esp_http_client_perform(client);
        if (err == ESP_OK)
        {
            ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
                     esp_http_client_get_status_code(client),
                     (int)esp_http_client_get_content_length(client));

            gettime = false;
            xSemaphoreGive(bind_ok);
        }
        else
        {
            ESP_LOGI(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
        }

        ESP_LOGI(TAG, "%s\n", local_response_buffer);
        esp_http_client_cleanup(client);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    vSemaphoreDelete(bind_ok);
    while (1)
    {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    // ESP_ERROR_CHECK(example_connect()); // 在menuconfig中wifi的账号密码

    xTaskCreate(&http_get_task, "http_get_task", 8192, NULL, 5, NULL);
}

